#pragma once

#include "hdmap/HDMapExports.hpp"
#include "hdmap/HDMapCommon.hpp"

namespace Navinfo
{
	namespace Engine
	{
		/**
		 *  @brief base element of land boundary informateion
		 */
		class HDMAP_API_PUBLIC HDMapLaneBoundaryElementInfo
		{
		public:
			HDMapLaneBoundaryElementInfo(DataSource::NDSLaneBoundarySequential &ndsLaneBoundarySequential);
			HDMapLaneBoundaryElementInfo() = default;
			virtual ~HDMapLaneBoundaryElementInfo() = default;

		public:
			/**
			 *  @brief Query whether it can cross the curb side of the road
			 */
			const bool GetOpenToCurbSide() const { return m_bOpenToCurbSide; }
			/**
			 *  @brief Query whether it can cross the middle side of the road
			 */
			const bool GetOpenToMiddleSide() const { return m_bOpenToMiddleSide; }
			/**
			 *  @brief get boundary type
			 */
			const HDMapLaneBoundaryType GetLaneBoundaryType() const { return m_laneBoundaryType; }
			/**
			 *  @brief get Marking color of boundary
			 */
			const MarkingColor GetLaneMarkingColor() const { return m_laneMarkingColor; }
			/**
			 *  @brief get material of boundary
			 */
			const HDMapLaneBoundaryMaterial GetLaneBoundaryMaterial() const { return m_laneBoundaryMaterial; }
			/**
			 *  @brief get length of boundary
			 */
			const uint16_t GetWidth() const { return m_nWidth; }
			/**
			 *  @brief get start position of boundary on road or lane
			 */
			const double GetStartPos() const { return m_dStartPos; }
			/**
			 *  @brief get end position of boundary on road or lane
			 */
			const double GetEndPos() const { return m_dEndPos; }
		private:
			bool						m_bOpenToCurbSide;		///< whether it can cross the curb side of the road
			bool						m_bOpenToMiddleSide;	///< whether it can cross the middle side of the road

			HDMapLaneBoundaryType		m_laneBoundaryType;		///< boundary type
			MarkingColor				m_laneMarkingColor;		///< color of marking
			HDMapLaneBoundaryMaterial	m_laneBoundaryMaterial;	///< materia of boundary
			
			uint16_t					m_nWidth;				///< width of boundary
			double						m_dStartPos;			///< start position of boundary on road or lane
			double						m_dEndPos;				///< end position of boundary on road or lane
		};

		/**
		 *  @brief multi lane boundary element
		 */
		class HDMAP_API_PUBLIC HDMapLaneBoundaryInfo
		{
		public:
			HDMapLaneBoundaryInfo(DataSource::NDSLaneBoundary &ndsLaneBoundary,bool bGeometryReverse);
			HDMapLaneBoundaryInfo() = default;
			virtual ~HDMapLaneBoundaryInfo() = default;

		public:
			/**
			 *  @brief Get a list of shape point coordinates for the lane boundary
			 *  @return a list of shape point coordinates
			 */
			const std::vector<Navinfo::Engine::Math::Vec3d>& GetGeometryPoints() const { return m_vtGeometryPoints; }

			
			/**
			 *  @brief Get the lane boundary element list
			 *  @return a list of Lane Boundary Elements
			 */
			const std::vector<std::shared_ptr<HDMapLaneBoundaryElementInfo>>& GetLaneBoundaryElements() const { return m_vtLaneBoundaryElements; }

		private:
			std::vector<Navinfo::Engine::Math::Vec3d>						m_vtGeometryPoints;
			std::vector<Navinfo::Engine::Math::LineSegment2d>				m_vtSegments;
			std::vector<std::shared_ptr< HDMapLaneBoundaryElementInfo>>		m_vtLaneBoundaryElements;
		};

		/**
		 *  @brief complex lane boundary
		 */
		class HDMAP_API_PUBLIC HDMapLaneBoundariesInfo
		{
		public:
			HDMapLaneBoundariesInfo() = default;
			HDMapLaneBoundariesInfo(DataSource::NDSLaneBoundaryGroup &ndsLaneBoundaryGroup);
			virtual ~HDMapLaneBoundariesInfo() = default;

		public:
			/**
			 *  @brief get lane boundary ID
			 */
			const uint64_t GetID() const { return m_nID; }
			/**
			 *  @brief Get the tile ID where the lane boundary is located
			 */
			const uint32_t GetTileID() const { return m_nTileID; }
			/**
			 *  @brief Get lane boundaries in the complex lane boundary
			 */
			const std::vector<std::shared_ptr< HDMapLaneBoundaryInfo>>& GetLaneBoundaries() const { return m_vtLaneBoundaries; }
			/**
			*  @brief get right side lane of this lane boundary
			*  @return right side lane
			*/
			const std::shared_ptr<HDMapLaneInfo> GetRightLane() const { return m_ptrRightLane.lock(); }
			/**
			*  @brief get left side lane of this lane boundary
			*  @return left side lane
			*/
			const std::shared_ptr<HDMapLaneInfo> GetLeftLane() const { return m_ptrLeftLane.lock(); }

		private:
			friend class HDMapImpl;
			uint64_t												m_nID;					///< 
			uint32_t												m_nTileID;				///< 
			std::vector<std::shared_ptr< HDMapLaneBoundaryInfo>>	m_vtLaneBoundaries;		///< 
			std::weak_ptr<HDMapLaneInfo>							m_ptrRightLane;			///< 
			std::weak_ptr<HDMapLaneInfo>							m_ptrLeftLane;			///< 
		};

	}
}
namespace Navinfo{
	namespace HDMap{
		typedef Navinfo::Engine::HDMapLaneBoundariesInfo LaneBoundaryGroup;
	}
}